﻿using Order.Common;
using Order.Common.Dto;
using Order.Domain.DomainService;
using Order.Domain.Repository;
using Order.EntityFrameworkCore;
using System;
using System.Threading.Tasks;
using Order.Common.WebApiClient;
using Polly;
using Order.Common.IntegratedEvent;
using Order.Common.Logger;
using Order.Domain.Entity;
using System.Collections.Generic;
using Cache.CSRedis;
using System.Linq;
using Microsoft.EntityFrameworkCore.Internal;
using System.Net;
using Product;
using AutoMapper;

namespace Order.CommandHandler
{
    public class OrderService : IOrderService
    {
        private readonly IOrderRepository _orderRepository;
        private readonly IUnitOfWork _unitOfWork;
        private readonly IRedisHelper _redisHelper;
        private readonly ISkuApi _skuApi;
        private readonly ILoggerHelper _loggerHelper;
        private readonly IntegratedEventService _integratedEventService;
        private readonly VerifySkuService _verifySkuService;
        private readonly VerifyCustomerService _verifyCustomerService;
        private readonly CreateOrderService _createOrderService;
        private readonly Producter.ProducterClient _producterClient;
        private readonly IMapper _mapper;

        private const string StockRedisKey = "StockRedisKey";

        public OrderService(
            ILoggerHelper loggerHelper,
            ISkuApi skuApi,
            IMapper mapper,
            IOrderRepository orderRepository,
            IUnitOfWork unitOfWork,
            IRedisHelper redisHelper,
            IntegratedEventService integratedEventService,
            VerifySkuService verifySkuService,
            VerifyCustomerService verifyCustomerService,
            CreateOrderService createOrderService,
            Producter.ProducterClient producterClient)
        {
            _skuApi = skuApi;
            _mapper = mapper;
            _unitOfWork = unitOfWork;
            _redisHelper = redisHelper;
            _loggerHelper = loggerHelper;
            _orderRepository = orderRepository;
            _integratedEventService = integratedEventService;
            _verifyCustomerService = verifyCustomerService;
            _verifySkuService = verifySkuService;
            _createOrderService = createOrderService;
            _producterClient = producterClient;
        }

        #region WebApiClient

        /// <summary>
        /// 1，验证sku的有效性
        /// 2，验证客户的有效性
        /// 3，生成订单号，创建订单
        /// 4，扣减库存
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResponseResult<string>> CreateOrderByWebApiClient(CreateOrderDto input)
        {
            try
            {
                List<OrderItem> orderItemList = new List<OrderItem>();
                foreach (var sku in input.SkuList)
                {
                    var orderItem = new OrderItem().SetOrderItem(sku.SkuPrice, sku.SkuQuantity, sku.SkuId, sku.SpuName);
                    orderItemList.Add(orderItem);
                }

                //验证sku的有效性
                var verifySkuResultMsg = await VerifySku(orderItemList);
                if (!string.IsNullOrWhiteSpace(verifySkuResultMsg))
                {
                    return new ResponseResult<string> { IsSucceed = false, Message = verifySkuResultMsg };
                }

                //验证客户的有效性
                var verifyCustomerResultMsg = await _verifyCustomerService.VerifyCustomer();
                if (!string.IsNullOrWhiteSpace(verifyCustomerResultMsg))
                {
                    return new ResponseResult<string> { IsSucceed = false, Message = verifySkuResultMsg };
                }

                //生成订单号，创建订单，扣减库存
                var result = await CreateOrderAsync(input.CustomerId, orderItemList).ContinueWith(async e =>
                {
                    //创建订单成功
                    if (e.Result.IsSucceed)
                    {
                        var deductionStockResult = await TryDeductionStockAsync(input.SkuList);
                        //扣减库存成功
                        if (deductionStockResult.IsSucceed)
                        {
                            return new ResponseResult<string> { IsSucceed = true, Message = "订单创建成功，扣减库存成功！" };
                        }
                        else
                        {
                            //扣减库存失败，作废订单
                            await RollbackOrder(e.Result.Message);
                            return new ResponseResult<string> { IsSucceed = false, Message = deductionStockResult.Message };
                        }
                    }
                    else
                    {
                        return new ResponseResult<string> { IsSucceed = false, Message = e.Result.Message };
                    }
                });
                return await result;
            }
            catch (Exception ex)
            {
                return new ResponseResult<string> { IsSucceed = false, Message = ex.Message };
            }
        }

        /// <summary>
        /// 验证sku的有效性
        /// </summary>
        /// <returns></returns>
        public async Task<string> VerifySku(List<OrderItem> orderItemList)
        {
            var resultMsg = string.Empty;
            //验证sku的有效性
            var verifySkuResult = await _skuApi.GetVerifySkuDto(orderItemList.Select(e => e.SkuId).Join(","));
            if (verifySkuResult.IsSucceed)
            {
                var verifySkuResultMsg = await _verifySkuService.VerifySku(verifySkuResult.Result, orderItemList);
                if (!string.IsNullOrWhiteSpace(verifySkuResultMsg))
                {
                    resultMsg = verifySkuResultMsg;
                }
            }
            return resultMsg;
        }

        /// <summary>
        /// 持久化订单
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        public async Task<ResponseResult<string>> CreateOrderAsync(string customerId, List<OrderItem> orderItemList)
        {
            var orderNo = await _createOrderService.CreateOrder(customerId, orderItemList);
            var isTrue = await _unitOfWork.CommitAsync();
            if (isTrue)
            {
                return new ResponseResult<string> { IsSucceed = true, Message = orderNo };
            }
            else
            {
                return new ResponseResult<string> { IsSucceed = false, Message = $"订单号：{orderNo},存储失败！" };
            }
        }

        /// <summary>
        /// 扣减库存
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        public async Task<ResponseResult<string>> TryDeductionStockAsync(List<SkuDto> skuList)
        {
            var policy = Policy.Handle<Exception>()
                .OrResult<ResponseResult<string>>(e => e.IsSucceed == false && e.StatusCode == HttpStatusCode.InternalServerError.ToString())
                .WaitAndRetryAsync(3, e => TimeSpan.FromSeconds(3), onRetry: (result, timeSpan) =>
                {
                    Task.Factory.StartNew(() =>
                    {
                        //记录重试的信息
                        _loggerHelper.LogInfo("扣减库存异常", result.Result.Message);
                    });
                });

            var result = await policy.ExecuteAsync(async () =>
              {
                  //扣减库存            
                  return await _skuApi.DeductionStockAsync(skuList);
              });

            return result;
        }

        /// <summary>
        /// 扣减库存失败后，作废掉订单
        /// </summary>
        /// <returns></returns>
        public async Task RollbackOrder(string orderNo)
        {
            var order = await _orderRepository.GetOrder(orderNo);
            order.SetStatus();
            await _unitOfWork.CommitAsync();
        }

        #endregion

        #region Grpc

        /// <summary>
        /// Grpc
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<ResponseResult<string>> CreateOrderByGrpc(CreateOrderDto input)
        {
            try
            {
                List<OrderItem> orderItemList = new List<OrderItem>();
                foreach (var sku in input.SkuList)
                {
                    var orderItem = new OrderItem().SetOrderItem(sku.SkuPrice, sku.SkuQuantity, sku.SkuId, sku.SpuName);
                    orderItemList.Add(orderItem);
                }

                //验证sku的有效性
                var verifySkuResultMsg = await VerifySku(orderItemList);
                if (!string.IsNullOrWhiteSpace(verifySkuResultMsg))
                {
                    return new ResponseResult<string> { IsSucceed = false, Message = verifySkuResultMsg };
                }

                //验证客户的有效性
                var verifyCustomerResultMsg = await _verifyCustomerService.VerifyCustomer();
                if (!string.IsNullOrWhiteSpace(verifyCustomerResultMsg))
                {
                    return new ResponseResult<string> { IsSucceed = false, Message = verifySkuResultMsg };
                }

                //生成订单号，创建订单，扣减库存
                var result = await CreateOrderAsync(input.CustomerId, orderItemList).ContinueWith(async e =>
                {
                    //创建订单成功
                    if (e.Result.IsSucceed)
                    {
                        var deductionStockResult = await TryDeductionStockByGrpcAsync(input.SkuList);
                        //扣减库存成功
                        if (deductionStockResult.IsSucceed)
                        {
                            return new ResponseResult<string> { IsSucceed = true, Message = "订单创建成功，扣减库存成功！" };
                        }
                        else
                        {
                            //扣减库存失败，作废订单
                            await RollbackOrder(e.Result.Message);
                            return new ResponseResult<string> { IsSucceed = false, Message = deductionStockResult.Message };
                        }
                    }
                    else
                    {
                        return new ResponseResult<string> { IsSucceed = false, Message = e.Result.Message };
                    }
                });
                return await result;
            }
            catch (Exception ex)
            {
                return new ResponseResult<string> { IsSucceed = false, Message = ex.Message };
                throw;
            }
        }

        public async Task<ResponseResult> TryDeductionStockByGrpcAsync(List<SkuDto> skuList)
        {
            var policy = Policy.Handle<Exception>()
                .OrResult<ResponseResult>(e => e.IsSucceed == false && e.StatusCode == HttpStatusCode.InternalServerError.ToString())
                .WaitAndRetryAsync(3, e => TimeSpan.FromSeconds(3), onRetry: (result, timeSpan) =>
                {
                    Task.Factory.StartNew(() =>
                    {
                        //记录重试的信息
                        _loggerHelper.LogInfo("扣减库存异常", result.Result.Message);
                    });
                });

            var result = await policy.ExecuteAsync(async () =>
            {
                SkuListRequest request = new SkuListRequest();              
                skuList.ForEach(e=> {
                    SkuRequest sr = new SkuRequest() 
                    { 
                        SkuId = e.SkuId,
                        SkuPrice = (float)e.SkuPrice,
                        SkuQuantity=e.SkuQuantity,
                        SpuName=e.SpuName
                    };
                    request.SkuList.Add(sr);
                });                
                //扣减库存            
                return await _producterClient.DeductionStockAsync(request);
            });

            return result;
        }

        #endregion

        #region

        #endregion

        #region Event

        public async Task<ResponseResult<string>> CreateOrderByEvent(CreateOrderDto input)
        {
            try
            {
                List<OrderItem> orderItemList = new List<OrderItem>();
                foreach (var sku in input.SkuList)
                {
                    var orderItem = new OrderItem().SetOrderItem(sku.SkuPrice, sku.SkuQuantity, sku.SkuId, sku.SpuName);
                    orderItemList.Add(orderItem);
                }

                //验证sku的有效性
                var verifySkuResultMsg = await VerifySku(orderItemList);
                if (!string.IsNullOrWhiteSpace(verifySkuResultMsg))
                {
                    return new ResponseResult<string> { IsSucceed = false, Message = verifySkuResultMsg };
                }

                //验证客户的有效性
                var verifyCustomerResultMsg = await _verifyCustomerService.VerifyCustomer();
                if (!string.IsNullOrWhiteSpace(verifyCustomerResultMsg))
                {
                    return new ResponseResult<string> { IsSucceed = false, Message = verifySkuResultMsg };
                }

                //生成订单号，创建订单，扣减库存
                var orderResult = await CreateOrderAsync(input.CustomerId, orderItemList);
                if (orderResult.IsSucceed) 
                {
                    var skuEventList = _mapper.Map<List<SkuEvent>>(input.SkuList);
                    var deductionStockEvent = new DeductionStockEvent(skuEventList);
                    await _integratedEventService.RabbitMqSendEventAsync(deductionStockEvent);                   
                }
                return new ResponseResult<string> { IsSucceed = true, Message = "创建成功！" };
            }
            catch (Exception ex)
            {
                return new ResponseResult<string> { IsSucceed = false, Message = ex.Message };
            }
        }

        #endregion
      
    }
}
